<script setup>
import {ref, nextTick, watch} from "vue"
import {storeToRefs} from "pinia";
import {Handle, useNode, useVueFlow} from "@vue-flow/core";
import {VueDraggable} from "vue-draggable-plus";
import {useUserProfile} from "@/stores/useUserProfile.js";


const userProfile = useUserProfile()
const {latestTelemetryData} = storeToRefs(userProfile)

const {nodes, updateNode} = useVueFlow()
const {node} = useNode()
const props = defineProps({
	position: {
		type: Object,
		required: true,
	},
	data: {},
	id: null
})

// 检查条目
const checkerList = ref([
	// {
	// 	value: "", label: "", rule: null, status: {label: "已执行", value: "success"}, expectedValue: "0"
	// },
	// {
	// 	value: "", label: "", rule: null, status: {label: "等待中", value: "warning"}, expectedValue: "0"
	// },
	// {
	// 	isAdvance: true,
	// 	value: "",
	// 	label: "",
	// 	rule: null,
	// 	status: {label: "未执行", value: "default"},
	// 	expectedValue: "0"
	// }
])

// 判定方式,
const ruleOptions = [
	{
		label: "大于(>)",
		value: ">"
	},
	{
		label: "小于(<)",
		value: "<"
	},
	{
		label: "大于等于(>=)",
		value: ">="
	},
	{
		label: "小于等于(<=)",
		value: "<="
	},
	{
		label: "等于(=)",
		value: "=="
	}
]

// 每个规则映射的对应行为
const ruleBehaviourMap = {
	"==": (x, y) => x.toString() === y.toString(),
	"=": (x, y) => x.toString() === y.toString(),
	">=": (x, y) => x >= y,
	"<=": (x, y) => x <= y,
	">": (x, y) => x > y,
	"<": (x, y) => x < y,
}


const onCreate = () => {
	return checkerList.value.push(
		{
			value: null, label: null, rule: null, status: {label: "未执行", value: "default"}
		}
	);
}
const onAdvanceCreate = () => {
	return checkerList.value.push(
		{isAdvance: true, value: "", label: "", rule: null, status: {label: "未执行", value: "default"}}
	);
}
const onRemove = (index) => {
	checkerList.value.splice(index, 1)
}

// 拖拽状态
const drag = ref(false)

function onStart() {
	drag.value = true
}

function onEnd() {
	console.log('onEnd')
	nextTick(() => {
		drag.value = false
	})
}

/**
 * 获取全部遥测名称转换成选项,
 */
const getSignalOptions = ref(
	latestTelemetryData.value ? latestTelemetryData.value.parsedData.map((item, index) => ({
		'label': item.label,
		'value': `${item.label}${index}`
	})) : []
)
watch(checkerList, (newValue) => {
	// 监听到判据器中发生任何变动,都会刷新此值
	updateNode(node.id, {data: {...node.data, checkerList: newValue}})
}, {deep: true})

/**
 * 给定一个node 检查当前判据器中所有条件
 */
const checkAll = (node) => {
    return new Promise((resolve, reject) => {
        if (node.data.checkerList.length === 0) {
            // 提示
            message.warning("没有创建任何条件,跳过当前判据")
            resolve()  // 如果没有检查条件，直接返回
            return
        }

        let allChecked = true

        // 创建观察停止函数
        for (let checker of node.data.checkerList) {
            if (!checker.label || checker.label.trim() === "" || checker.stopWatch != null) {
                continue
            }

            // 创建观察停止函数
            checker.stopWatch = watch(latestTelemetryData, (newValue) => {
                let latestResp = latestTelemetryData.value.parsedData.find(resp => resp.label === checker.label)

                if (ruleBehaviourMap[checker.rule](latestResp?.value, checker.expectedValue)) {
                    checker.status = { label: "已执行", value: "success" }
                    // 匹配成功后停止观察
                    checker.stopWatch()
                    checker.stopWatch = null // 清除停止函数引用
                    console.log(`检查器 ${checker.label} 已通过，不再监听。`)
                } else {
                    // 检查不通过时的处理逻辑
                    checker.status = { label: "等待中", value: "warning" }
                    console.log(`检查器 ${checker.label} 未通过，继续监听。`)
                }
            })
        }

        // 每秒检查一次判据状态
        const checkInterval = setInterval(() => {
            // 判断所有判据是否已通过
            if (node.data.checkerList.every(checker => checker.status.value === "success")) {
                clearInterval(checkInterval)
                resolve()  // 所有判据通过，resolve
            }
        }, 1000)
    })
}

node.data.callback = checkAll
const allValid = ref(false)

// 监视每个判据是否全部通过
const validWatch = () => {
	// 每个判据均通过时设置为放行状态(存在任意一个非success的值,则代表还有未通过的项目)
	allValid.value = !checkerList.value.find(checker => checker.status.value !== "success")
	if (allValid.value) {
		node.data.allValid = true
		validWatch()
	}
}

</script>

<template>
	<n-card class="hover:bg-sky-900/25" header-class="pt-1 pb-1">
		<template #header>
			<n-text>状态:{{ node.data.execuated ? "已执行" : "未执行" }}</n-text>
		</template>
		<template #default>
			<div class="border border-sky-700 p-1 flex flex-col gap-1 rounded">
				<Handle type="source" :position="data.sourcePosition"/>
				<Handle type="target" :position="data.targetPosition"/>
				<div class="nodrag nowheel flex flex-col gap-2">
					<n-space>
						<n-tag type="info">步骤:{{ id }}</n-tag>
						<n-tag type="warning">类型:{{ data.label }}</n-tag>
						<n-button secondary type="success" size="small" class="active:bg-sky-100/75" @click="onCreate">
							增加判据
						</n-button>
						<n-button secondary type="info" size="small" class="active:bg-sky-100/75"
								  @click="onAdvanceCreate">
							高级判据
						</n-button>
						<n-button secondary type="error" size="small" class="active:bg-sky-100/75" @click="checkAll">
							检查全部
						</n-button>
					</n-space>
					<n-space vertical v-if="checkerList.length>0">
						<VueDraggable
							v-model="checkerList"
							:animation="150"
							handle=".handle"
							class="flex flex-col gap-1 w-300px rounded pe-4"
							@start="onStart"
							@end="onEnd"
						>

							<TransitionGroup
								type="transition"
								:name="!drag ? 'fade' : undefined"
							>
								<div v-for="(item, index) in checkerList" :key="item">

									<!--
									  通常，path 的变化会导致 form-item 验证内容或规则的改变，所以 naive-ui 会清理掉
									  表项已有的验证信息。但是这个例子是个特殊情况，我们明确的知道，path 的改变不会导致
									  form-item 验证内容和规则的变化，所以就 ignore-path-change
									-->
									<div class="flex gap-1">
										<n-tag type="info" size="large" class="text-base handle">
											顺序: {{ index + 1 }}
										</n-tag>
										<n-tag :type="item.status.value" size="large">
											{{ item.status.label }}
										</n-tag>
										<div v-if="!item.isAdvance" class="flex gap-2 items-center">
											<n-select class="w-48" :options="getSignalOptions"
													  placeholder="请选择信号名称"
													  v-model:value="checkerList[index].label"
													  :on-update:value="(value, option) =>checkerList[index].label = option.label"
											></n-select>


											<n-select class="w-32" :options="ruleOptions"
													  placeholder="判据条件"
													  v-model:value="checkerList[index].rule"></n-select>

											<!--未来可以升级成自动识别label来变更为枚举值选择框-->
											<n-input
												class="w-48"
												v-model:value="item.expectedValue"
												placeholder="输入预期值"
												@keydown.enter.prevent
											/>
										</div>
										<div v-else class="flex gap-2 items-center w-full">
											<n-select class="w-48" :options="ruleOptions"
													  placeholder="请选择信号名称"
													  v-model:value="checkerList[index].label"></n-select>
											<n-input
												placeholder="输入代码(信号值会自动注入到代码中) (x) => x >= 90"></n-input>
										</div>
										<n-button type="error" secondary @click="onRemove(index)">移除</n-button>

									</div>

								</div>
							</TransitionGroup>
						</VueDraggable>

					</n-space>
					<n-space vertical v-else>
						<n-empty>无判据</n-empty>
					</n-space>
				</div>
			</div>

		</template>


	</n-card>

</template>

<style scoped>
.fade-move,
.fade-enter-active,
.fade-leave-active {
	transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}

.fade-enter-from,
.fade-leave-to {
	opacity: 0;
	transform: scaleY(0.01) translate(30px, 0);
}

.fade-leave-active {
	position: absolute;
}
</style>